from time import sleep
from wsgiref import headers
import serial
import struct
import threading
import queue

# 创建一个队列
zw_q = queue.Queue()

ser = serial.Serial('com5', 57600, timeout=1)

int2bytes = lambda data:int(data).to_bytes(2, byteorder='big', signed=False)
def calculate_checksum(data: bytearray) -> int:
    checksum = 0
    # 按 16 位（2 字节）分组进行累加
    for i in data:
        checksum = checksum + i
    return checksum

def read_serial_data():
    header = bytearray(0)
    while True:
        if ser.in_waiting > 0:
            header.extend(ser.read(1))
            # header.append(ser.read(1))
            # print('len = {}'.format(len(header)))
            if(len(header) == 7):
                # print(header.hex())
                if(header.hex() == 'ef01ffffffff07'):
                    size_arrry = ser.read(2)
                    size = struct.unpack('>h',size_arrry)
                    format_s = '>{}Bh'.format(size[0]-2)
                    data_array = ser.read(size[0])
                    data = data_array[:-2]
                    check = struct.unpack('>h',data_array[-2:])
                    # data,check = struct.unpack(format_s,data_array)
                    # print(data)
                    check_c = calculate_checksum(bytearray(b'\x07')+size_arrry+data_array[:-2])
                    if(check_c == check[0]):
                        zw_q.put(data)
                    header.clear()

            # if header.hex() == 'efaa':
            #     msg_type,size=struct.unpack('>Bh',ser.read(3))
            #     data = ser.read(size)
            #     check = ser.read(1)
            #     print(f'recv: {msg_types[msg_type]} size: {size} ')
            #     if msg_type == 0x01:
            #         get_note_data(data)
            #     elif msg_type == 0x00:
            #         get_reply_data(data)
            #     else:
            #         print(f'data: {" ".join(f"{b:02x}" for b in data)} check: {check.hex()}')

def PS_GetImage():
    sync_word = 0xef01
    addr = 0xffffffff
    pake_flag = 0x01
    size = 0x0003
    cmd = 0x01
    sync_paket = struct.pack('>H I',sync_word,addr)
    data_paket = struct.pack('>B H B', pake_flag, size, cmd)
    # packet = struct.pack('>H B h BB', sync_word, msgid, size, need_poweroff, timeout)
    parity_code = calculate_checksum(data_paket)
    # packet += parity_code.to_bytes()
    packet = sync_paket + data_paket + int2bytes(parity_code)
    return packet


def PS_GenChar():
    sync_word = 0xef01
    addr = 0xffffffff
    pake_flag = 0x01
    size = 0x0004
    cmd = 0x02
    data = 0x01
    sync_paket = struct.pack('>H I', sync_word, addr)
    data_paket = struct.pack('>B H B B', pake_flag, size, cmd, data)
    # packet = struct.pack('>H B h BB', sync_word, msgid, size, need_poweroff, timeout)
    parity_code = calculate_checksum(data_paket)
    # packet += parity_code.to_bytes()
    packet = sync_paket + data_paket + int2bytes(parity_code)
    return packet

def PS_Search():
    sync_word = 0xef01
    addr = 0xffffffff
    pake_flag = 0x01
    size = 0x0008
    cmd = 0x04
    BufferID = 0x01
    StartPage = 0
    PageNum = 0x64
    sync_paket = struct.pack('>H I', sync_word, addr)
    data_paket = struct.pack('>B H B B H H', pake_flag, size, cmd, BufferID,StartPage,PageNum)
    # packet = struct.pack('>H B h BB', sync_word, msgid, size, need_poweroff, timeout)
    parity_code = calculate_checksum(data_paket)
    # packet += parity_code.to_bytes()
    packet = sync_paket + data_paket + int2bytes(parity_code)
    return packet



threading.Thread(target=read_serial_data, daemon=True).start()


def PS_Search_quqe_get():
    try:
        data = zw_q.get(timeout=1)
        msg_types={
            00:'搜索到指纹',
            0x01:'示收包有错',
            0x09:'没搜索到；此时页码与得分为0',
            0x17:'残留指纹或两次釆集之间手指没有移动过',
            0x18:'写FLASH出错',
            0x31:'功能与加密等级不匹配',
            0x35:'非法数据'
            }
        print(msg_types[data[0]])
        if(data[0] == 0):
            status,PageID,MatchScore = struct.unpack('>BHH',data)
            print('指纹ID：{}'.format(PageID))
            print('得分：{}'.format(MatchScore))
        # if data == 0:
        #     PS_Search()
        #     print(f'data: {" ".join(f"{b:02x}" for b in data)}')
        #     ser.write(data)
            
    except queue.Empty:
        print('接收超时')

def PS_GenChar_quqe_get():
    try:
        data = zw_q.get(timeout=1)
        msg_types={
            00:'生成特征成功',
            0x06:'指纹图像太乱而生不成特征',
            0x07:'指纹图像正常，但特征点太少而生不成特征',
            0x08:'当前指纹特征与之前特征之间无关联',
            0x0a:'合并失败',
            0x15:'图像缓冲区内没有有效原始图而生不成图像',
            0x28:'当前指纹特征与之前特征之间有关联'
            }
        print(msg_types[data[0]])
        if data[0] == 0:
            data = PS_Search()
            print(f'data: {" ".join(f"{b:02x}" for b in data)}')
            ser.write(data)
            PS_Search_quqe_get()
    except queue.Empty:
        print('接收超时')

def PS_GetImage_quqe_get():
    try:
        data = zw_q.get(timeout=1)
        msg_types=['获取图像成功','收包有错','示传感器上无手指']
        print(msg_types[data[0]])
        if(data[0] == 0):
            data = PS_GenChar()
            print(f'data: {" ".join(f"{b:02x}" for b in data)}')
            ser.write(data)
            PS_GenChar_quqe_get()
    except queue.Empty:
        print('接收超时')



# while True:
#     print('1.获取图像')
#     cmd = input('请输入命令:')
#     if cmd=='1':
#         data = PS_GetImage()
#         print(f'data: {" ".join(f"{b:02x}" for b in data)}')
#         ser.write(data)
#         PS_GetImage_quqe_get()
#     else:
#         print('未知命令')
#         continue


while True:   
    data = PS_GetImage()
    print(f'data: {" ".join(f"{b:02x}" for b in data)}')
    ser.write(data)
    PS_GetImage_quqe_get()
    sleep(0.8)
